using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;

using PHSRAG.Insight21.BusinessObjects;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using PHSRAG.Utility;

namespace PHSRAG.Insight21.ClinicalTrials
{

   /// <summary>
   /// The BudgetMilestoneVisits class represents a collection of BudgetMilestoneVisit objects.  It is 
   /// responsible for loading and saving the Budget Milestone Visits
   /// </summary>
   public class BudgetMilestoneVisits : SaveableBusinessObject, IEnumerable
   {

      #region Constants
      private const string BudgetMilestoneVisitsKey = "BudgetMilestoneVisits_0A7C68A2-2BFA-4e01-9207-141743F8225A";
      private const string TableName = "BudgetMilestoneVisits";
      #endregion

      #region Instance Variables
      private ArrayList budgetMilestoneVisits = new ArrayList( );
      private SqlCommand updateBudgetMilestoneVisitsCommand;
      private SqlCommand deleteBudgetMilestoneVisitsCommand;
      #endregion

      #region Constructor
      /// <summary>
      /// Initialize the base class with the specified cache policy and create the data container.
      /// </summary>
      public BudgetMilestoneVisits( ICachePolicy cachePolicy ) : base ( cachePolicy )
      {
         DataContainer = new DataSet( );
      }
      #endregion
   
      #region Base Methods
      /// <summary>
      /// Cache this instance using the prevalent cache policy.
      /// </summary>
      public override void Cache( )
      {
         CachePolicy.Cache( BudgetMilestoneVisitsKey, this );
      }

      /// <summary>
      /// Remove this instance from the cache using the prevalent cache policy.
      /// </summary>
      public override void UnCache( )
      {
         CachePolicy.UnCache( BudgetMilestoneVisitsKey );
      }

      /// <summary>
      /// Loads Budget Milestone Visit details pertaining to a specific budget.
      /// </summary>
      /// <param name="connectionString">Connection string to the database</param>
      /// <param name="args">Object array which must contain the relate class and relate id</param>
      public override void Load( string connectionString, params object[] args )
      {
         if ( args.Length != 2 )
            throw new Exception("BudgetMilestoneVisits load requires a relate class and relate id.");
			
         DataAccess.LoadDataSet( DataContainer, TableName, connectionString, "GetClinicalTrialBudgetMilestoneVisits", 
            Utility.DataAccess.BuildSqlParameterArray( "@relateClass", SqlDbType.VarChar, args[0],
                                                       "@relateId", SqlDbType.Int, args[1] ) );

         if ( DataContainer.Tables.Count == 0 )
            throw new Exception("Failed to load Budget Milestone Visit information.");

         foreach( DataRow budgetMilestoneVisitRow in DataContainer.Tables[TableName].Rows )
         {
            budgetMilestoneVisits.Add( new BudgetMilestoneVisit( CachePolicy, budgetMilestoneVisitRow ) );
         }
      }

      /// <summary>
      /// Saves Budget Milestone Visit details associated with this budget.  
      /// </summary>
      /// <param name="connectionString">Connection string to the database</param>
      /// <param name="args">Optional parameters (ignored)</param>
      public override void Save( string connectionString, params object[] args )
      {
         SqlConnection connection = new SqlConnection( connectionString );
         SqlTransaction transaction = null;
         try
         {
            connection.Open( );
            transaction = connection.BeginTransaction( );
            BuildCommands( );
            updateBudgetMilestoneVisitsCommand.Connection = connection;
            updateBudgetMilestoneVisitsCommand.Transaction = transaction;
            deleteBudgetMilestoneVisitsCommand.Connection = connection;
            deleteBudgetMilestoneVisitsCommand.Transaction = transaction;

            SqlDataAdapter adapter = new SqlDataAdapter( );
            adapter.InsertCommand = updateBudgetMilestoneVisitsCommand;
            adapter.UpdateCommand = updateBudgetMilestoneVisitsCommand;
            adapter.DeleteCommand = deleteBudgetMilestoneVisitsCommand;
            adapter.Update( DataContainer, TableName );
            transaction.Commit( );
         }
         catch( Exception e )
         {
            transaction.Rollback( );
            throw(new Exception(@"Error saving Budget Milestone Visits to the database.", e));
         }
         finally
         {
            if ( connection.State != ConnectionState.Closed )
               connection.Close( );
            transaction.Dispose( );
         }
      }
      #endregion

      #region Private Methods
      private void BuildCommands( )
      {
         if ( updateBudgetMilestoneVisitsCommand == null )
         {
            updateBudgetMilestoneVisitsCommand = new SqlCommand( );
            updateBudgetMilestoneVisitsCommand.CommandText = "UpdateClinicalTrialBudgetMilestoneVisits";
            updateBudgetMilestoneVisitsCommand.CommandType = CommandType.StoredProcedure;
			updateBudgetMilestoneVisitsCommand.CommandTimeout = Convert.ToInt32(Utility.Settings.GetKeyValue("Database.Insight.CommandTimeout", "0"));
			SqlParameter paramId = new SqlParameter( "@budgetMilestoneVisitId", SqlDbType.Int );
            paramId.SourceColumn = "Id";
            paramId.Direction = ParameterDirection.InputOutput;
            updateBudgetMilestoneVisitsCommand.Parameters.Add( paramId );
            updateBudgetMilestoneVisitsCommand.Parameters.Add( "@budgetVisitId", SqlDbType.Int ).SourceColumn = "ClinicalTrialBudgetVisitId";
            updateBudgetMilestoneVisitsCommand.Parameters.Add( "@relateClass", SqlDbType.VarChar ).SourceColumn = "RelateClass";
            updateBudgetMilestoneVisitsCommand.Parameters.Add( "@relateId", SqlDbType.Int ).SourceColumn = "RelateId";
            updateBudgetMilestoneVisitsCommand.Parameters.Add( "@required", SqlDbType.Bit ).SourceColumn = "Required";
            updateBudgetMilestoneVisitsCommand.Parameters.Add( "@standardOfCare", SqlDbType.Bit ).SourceColumn = "StandardOfCare";
         }

         if ( deleteBudgetMilestoneVisitsCommand == null )
         {
            deleteBudgetMilestoneVisitsCommand = new SqlCommand( );
            deleteBudgetMilestoneVisitsCommand.CommandText = "DeleteClinicalTrialBudgetMilestoneVisits";
            deleteBudgetMilestoneVisitsCommand.CommandType = CommandType.StoredProcedure;
			deleteBudgetMilestoneVisitsCommand.CommandTimeout = Convert.ToInt32(Utility.Settings.GetKeyValue("Database.Insight.CommandTimeout", "0"));
			SqlParameter paramDeleteId = new SqlParameter( "@budgetMilestoneVisitId", SqlDbType.Int );
            paramDeleteId.SourceColumn = "Id";
            paramDeleteId.Direction = ParameterDirection.Input;
            deleteBudgetMilestoneVisitsCommand.Parameters.Add( paramDeleteId );
         }
      }
      #endregion
      
      #region IEnumerable Methods
      /// <summary>
      /// Gets an IEnumerator interface.  Required for implementation of IEnumerable
      /// </summary>
      /// <returns>IEnumerator</returns>
      public IEnumerator GetEnumerator( )
      {
		   return budgetMilestoneVisits.GetEnumerator( );
      }
      #endregion

      
      #region Public Collection helpers
      /// <summary>
      /// The Count property returns the number of items in the Budget Milestone Visits collection
      /// </summary>
      public int Count
      {
         get
         {
            return budgetMilestoneVisits.Count;
         }
      }

      /// <summary>
      /// Indexer to get a specific Budget Milestone Visit from the collection
      /// </summary>
      public BudgetMilestoneVisit this[int index]
      {
         get
         {
            return (BudgetMilestoneVisit)budgetMilestoneVisits[ index ];
         }
      }
      #endregion

      #region Public Methods
      /// <summary>
      /// Creates a new BudgetMilestoneVisit and adds it to the collection.  Also sets default
      /// properties on the BudgetMilestoneVisit
      /// </summary>
      /// <param name="visitId">Id of the BudgetVisit to associate with the new BudgetMilestoneVisit</param>
      /// <param name="relateClass">RelateClass to associated with the new BudgetMilestoneVisit</param>
      /// <returns>BudgetMilestoneVisit</returns>
      public BudgetMilestoneVisit CreateNewBudgetMilestoneVisit( int visitId, string relateClass )
      {
         DataRow newRow = DataContainer.Tables[TableName].NewRow( );
         DataContainer.Tables[TableName].Rows.Add( newRow );
         BudgetMilestoneVisit newBudgetMilestoneVisit = new BudgetMilestoneVisit( CachePolicy, newRow );
         newBudgetMilestoneVisit.BudgetVisitId = visitId;
         newBudgetMilestoneVisit.RelateClass = relateClass;
         // We need to set required and SOC to something here because they are required in the DB.  
         // Normally these are added by web controls which set the value by themselves.  But on 
         // the budget setup page, it's possible to raise the number of visits, which adds BMVs
         // at that point (with no web control) so set them manually by default
         newBudgetMilestoneVisit.Required = false;
         newBudgetMilestoneVisit.StandardOfCare = false;
         budgetMilestoneVisits.Add( newBudgetMilestoneVisit );
		   return newBudgetMilestoneVisit;
      }

      /// <summary>
      /// Removes a specific BudgetMilestoneVisit from the collection.  Must call save on BudgetMilestoneVisits
      /// to save this change to the database.
      /// </summary>
      /// <param name="budgetExpense">BudgetExpense to remove from the collection.</param>
      public void RemoveBudgetMilestoneVisit( BudgetMilestoneVisit budgetMilestoneVisit )
      {
         DataContainer.Tables[TableName].Select( string.Format( "Id = {0}", budgetMilestoneVisit.Id ) )[0].Delete( );
         budgetMilestoneVisits.Remove( budgetMilestoneVisit );
      }
      #endregion

   }// END CLASS DEFINITION BudgetMilestoneVisits
}